﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Reporting.WinForms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Drawing.Printing;
using System.ComponentModel;
using System.Drawing.Imaging;
using System.IO;
namespace Billing.Reports
{
    public class ReportManager
    {
        private int m_currentPageIndex;
        private IList<Stream> m_streams;
        private IList<ReportParameter> mParameters;
        public IList<ReportParameter> Parameters
        {
            get { return mParameters; }
        }

        public void LoadReport(string ReportName, IList<ReportParameter> parameters)
        {
            m_currentPageIndex = 0;
            Report report = null;
            mParameters = parameters;
            object obj = Activator.CreateInstance(typeof(ServerReport), true);
            ServerReport SR = (ServerReport)obj;
            SR.ReportServerUrl = new Uri(Billing.SettingManager.getSetting("ReportService"));
            SR.ReportPath = ReportName;
            SR.ReportServerCredentials.NetworkCredentials = new System.Net.NetworkCredential(
                        Billing.SettingManager.getSetting("ReportServiceUser"),
                        Billing.SettingManager.getSetting("ReportServicePassword"));
            report = SR;

            if (this.Parameters != null)
                report.SetParameters(Parameters);
            Export(report);
        }

        private void Export(Report report)
        {
            string deviceInfo;
            deviceInfo =
            "<DeviceInfo>" +
            "  <OutputFormat>EMF</OutputFormat>" +
            "</DeviceInfo>";

            Warning[] warnings;
            string mimeType;
            string encoding;
            string fileNameExtencion;
            string[] streams;
            m_streams = new List<Stream>();
            int m_numberOfPages;

            byte[] buffer = report.Render("Image", deviceInfo, out mimeType, out encoding, out fileNameExtencion, out streams, out warnings);

            m_numberOfPages = streams.Length + 1;
            CreateStream(buffer);

            for (int pageIndex = 1; pageIndex < m_numberOfPages; pageIndex++)
            {
                deviceInfo =
                String.Format(@"<DeviceInfo><OutputFormat>{0}</OutputFormat><StartPage>{1}</StartPage></DeviceInfo>", "emf", pageIndex + 1);
                buffer = null;
                buffer = report.Render("Image", deviceInfo, out mimeType, out encoding, out fileNameExtencion, out streams, out warnings);
                CreateStream(buffer);
            }
            foreach (Stream s in m_streams)
            {
                s.Seek(0, SeekOrigin.Begin);
            }
            OnPrint(new CancelEventArgs(false));
        }

        private void OnPrint(CancelEventArgs e)
        {
            if (!e.Cancel)
            {
                string printerName = new PrinterSettings().PrinterName;
                if (m_streams == null || m_streams.Count == 0)
                    return;

                PrintDocument printDoc = new PrintDocument();
                printDoc.PrinterSettings.PrinterName = printerName;             
                printDoc.PrintController = new StandardPrintController();


                if (!printDoc.PrinterSettings.IsValid)
                {
                    string msg = String.Format("Can't find printer \"{0}\".", printerName);
                    // MessageBox.Show(msg, "Print Error");
                    return;
                }

                printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
                printDoc.EndPrint += new PrintEventHandler(printDoc_EndPrint);
                printDoc.Print();
            }
        }

        private Stream CreateStream(byte[] buffer)
        {
            Stream stream = null;
            if (buffer == null)
            {
                stream = new MemoryStream();
            }
            else
            {
                stream = new MemoryStream(buffer);
            }

            m_streams.Add(stream);
            return stream;
        }

        private void PrintPage(object sender, PrintPageEventArgs ev)
        {
            Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
            ev.Graphics.DrawImage(pageImage, ev.PageBounds);
            m_currentPageIndex++;
            ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
        }

        private void printDoc_EndPrint(object sender, PrintEventArgs e)
        {
            if (m_streams != null)
            {
                foreach (Stream stream in m_streams)
                    stream.Close();
                m_streams = null;
            }
        }

    }
}
